/**
 * 
 */
package badugi;

import java.util.ArrayList;
import java.util.Collections;

import bot.BotClient;

/** Class WhoWon is a typical logical class, it answers the question which hand wins, with the rules of Badugi poker game.
 * @author aleks
 *
 */
public class WhoWon {

	/**
	 * It compares (using recursion) two ranks with the same nr of elements to say, witch of them is better.
	 * @param rank0
	 * @param rank1
	 * @param index
	 * @return -1 - a draw; 0 - player 0; 1 - player 1;
	 */
	private static int compareCards(ArrayList<Card> rank0, ArrayList<Card> rank1, int index) {
		if (index < 0) {
			return -1;
		}
		else if (rank0.get(index).getValue() < rank1.get(index).getValue()) {
			return 0;
		}
		else if (rank0.get(index).getValue() > rank1.get(index).getValue()) {
			return 1;
		}
		else {
			return compareCards(rank0, rank1, index-1);
		}
	}
	
	/**
	 * 
	 * @param colorOfTheCard
	 * @param rank
	 * @param index
	 * @return true if colorOfTheCard is new and unique
	 */
	private static boolean checkIfThatColorWas(int colorOfTheCard, ArrayList<Card> rank, int index) {
		for (int i = 0; i < rank.size(); i++) {
			if (rank.get(i).getColor() == colorOfTheCard) {
				return false;
			}
		}
		return true;
	}
	
	/**
	 * 
	 * @param valueOfTheCard
	 * @param rank
	 * @param index
	 * @return true if valueOfTheCard is new and unique
	 */
	private static boolean checkIfThatValueWas(int valueOfTheCard, ArrayList<Card> rank, int index) {
		for (int i = 0; i < rank.size(); i++) {
			if (rank.get(i).getValue() == valueOfTheCard) {
				return false;
			}
		}
		return true;
	}
	
	/**
	 * It compares two ranks and decide, which of them is better. It is when have more cards than the other. If they have the same number of cards, it uses compareCards() method.
	 * @param rank0
	 * @param rank1
	 * @return 0 if the first parameter (rank0) is better; 1 if the second parameter (rank1) is better, -1 if is a draw
	 */
	private static int compareTwoRanks(ArrayList<Card> rank0, ArrayList<Card> rank1) {
		if (rank0.size() > rank1.size()) {
			return 0;
		}
		else if (rank0.size() < rank1.size()) {
			return 1;
		}
		else {
			return compareCards(rank0, rank1, rank0.size()-1);
		}
	}
	
	/**
	 * It takes a hand of the player and make a rank. Additionally, it checks various combination and chooses the best one.
	 * @param hand
	 * @return the best possible rank
	 */
	private static ArrayList<Card> makeARank(Hand hand) {
		ArrayList<ArrayList<Card>> allPossibleRanks = new ArrayList<ArrayList<Card>>();
		ArrayList<Card> rank;
		for (int j = 0; j < 4; j++) {
			allPossibleRanks.add(new ArrayList<Card>());
			allPossibleRanks.get(j).add(hand.getOneCard(0));
			for (int i = 1; i < 4; i++) {
				if (checkIfThatColorWas(hand.getColorOfTheCard(i), allPossibleRanks.get(j), i)) {
					if (checkIfThatValueWas(hand.getValueOfTheCard(i), allPossibleRanks.get(j), i)) {
						allPossibleRanks.get(j).add(hand.getOneCard(i));
					}
				}
			}
			hand.mixFirstAndLastCard();
		}
		int max = 0;
		int indexOfMax = 0;
		for (int k = 0; k < 4; k++) {
			if (allPossibleRanks.get(k).size() > max) {
				max = allPossibleRanks.get(k).size();
				indexOfMax = k;
			}
		}
		rank = allPossibleRanks.get(indexOfMax);
		Collections.sort(rank);
		return rank;
	}
/**
 * It could be used by bot.
 * @param content a property prepared String
 * @return Cards in strong in correct format
 */
	public static String makeMeARankFromString(String content) {
		try {
			String rank = "";
			String[] cards = content.split("/");
			Card firstCard = new Card(Integer.parseInt(cards[0].substring(0, 1)), Integer.parseInt(cards[0].substring(2, cards[0].length())));
			Card secondCard = new Card(Integer.parseInt(cards[1].substring(0, 1)), Integer.parseInt(cards[1].substring(2, cards[1].length())));
			Card thirdCard = new Card(Integer.parseInt(cards[2].substring(0, 1)), Integer.parseInt(cards[2].substring(2, cards[2].length())));
			Card fourthCard = new Card(Integer.parseInt(cards[3].substring(0, 1)), Integer.parseInt(cards[3].substring(2, cards[3].length())));
			Hand myHand = new Hand(firstCard, secondCard, thirdCard, fourthCard);
			ArrayList<Card> listWithRank = makeARank(myHand);
			for (int i = 0; i < listWithRank.size(); i++) {
				rank += listWithRank.get(i).toString();
				if (i != listWithRank.size()-1 ) {
					rank += "/";
				}
			}
			return rank;
		}
		catch (Exception e) {
			return e.getMessage();
		}
	}
	
	/**
	 * That public method compares ranks and answers, who win (has the best hand).
	 * @param allHands
	 * @return (0..(nrOfPlayers-1)) int when some of them wins; multi-digit if is a draw.
	 */
	public static int CheckWhoWon(Hand[] allHands) {
		int nrOfPlayers = allHands.length;
		int playerWhoWon = 0;
		ArrayList<ArrayList<Card>> ranks = new ArrayList<ArrayList<Card>>();
		for (int k = 0; k < nrOfPlayers; k++) {
			ranks.add(makeARank(allHands[k]));
		}
		ArrayList<Integer> tableOfDraw = new ArrayList<Integer>();
		int tempWinner;
		tempWinner = compareTwoRanks(ranks.get(0), ranks.get(1));
		if (tempWinner == 0) {
			playerWhoWon = 0;
		}
		else if (tempWinner == 1) {
			playerWhoWon = 1;
		}
		else if (tempWinner == -1) {
			playerWhoWon = 0;
			tableOfDraw.add(new Integer(0));
			tableOfDraw.add(new Integer(1));
		}
		if (nrOfPlayers > 2) {
			tempWinner = compareTwoRanks(ranks.get(playerWhoWon), ranks.get(2));
			if (tempWinner == 0) {
			}
			else if (tempWinner == 1) {
				playerWhoWon = 2;
			}
			else if (tempWinner == -1) {
				//tableOfDraw.add(new Integer(playerWhoWon));
				tableOfDraw.add(new Integer(2));
			}
			if (nrOfPlayers > 3) {
				tempWinner = compareTwoRanks(ranks.get(playerWhoWon), ranks.get(3));
				if (tempWinner == 0) {
				}
				else if (tempWinner == 1) {
					playerWhoWon = 3;
				}
				else if (tempWinner == -1) {
					//tableOfDraw.add(new Integer(playerWhoWon));
					tableOfDraw.add(new Integer(3));
				}
				if (nrOfPlayers > 4) {
					tempWinner = compareTwoRanks(ranks.get(playerWhoWon), ranks.get(4));
					if (tempWinner == 0) {
					}
					else if (tempWinner == 1) {
						playerWhoWon = 4;
					}
					else if (tempWinner == -1) {
						//tableOfDraw.add(new Integer(playerWhoWon));
						tableOfDraw.add(new Integer(4));
					}
					if (nrOfPlayers > 5) {
						tempWinner = compareTwoRanks(ranks.get(playerWhoWon), ranks.get(5));
						if (tempWinner == 0) {
						}
						else if (tempWinner == 1) {
							playerWhoWon = 5;
						}
						else if (tempWinner == -1) {
							//tableOfDraw.add(new Integer(playerWhoWon));
							tableOfDraw.add(new Integer(5));
						}
						
					}
				}
			}
		}
		if (tableOfDraw.size() != 0) {
			boolean draw = false;
			for (int i = 0; i < tableOfDraw.size(); i++) {
				if (playerWhoWon == tableOfDraw.get(i).intValue()) draw = true; 
			}
			if (draw) {
				int x = 1;
				int take = 0;
				for (int i = 0; i < tableOfDraw.size(); i++) {
					take += tableOfDraw.get(i).intValue() * x;
					x *= 10;
				}
				return take;
			}
			else return playerWhoWon;
		}
		else {
			return playerWhoWon;
		}
	}
}